<?php
declare(strict_types=1);

namespace App\Utils\Other\Payment\Sumpay;

use App\Exception\InternalException;
use Hyperf\Collection\Arr;
use function App\Utils\Common\SumpayRsa\splic;
use function App\Utils\Common\SumpayRsa\verify;
use function Hyperf\Translation\__;

/**
 * 微信小程序端
 * @package App\Utils\Other\Payment\Sandpay
 */
Class Mini extends App {

    /**
     * 支付
     * @param array $params
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function pay(array $params): array
    {
        $this->setConfig([
            'encrypt_fields' => [
                'identity', 'ext_user_info'
            ],
            'json_fields' => [
                'benefit_bean_list'
            ],
            'special_fields' => [
                'terminal_info', 'longitude', 'latitude', 'notify_url',
                'goods_name', 'remark', 'attach', 'share_benefit_exp',
                'actual_shop', 'trade_info', 'detail', 'wx_terminal_info',
                'scene_info', 'detail', 'ali_terminal_info'
            ]
        ]);

        $params['service'] = 'fosun.sumpay.api.trade.mini.program.order.apply';
        $params['mer_no'] = $this->getConfig('mer_no');
        $params['sp_app_id'] = $this->getConfig('app_id');
        $params['business_code'] = '25';
        $params['need_notify'] = '1';

        [$params, $response, $body] = $this->request($params);
        $body = json_decode($body['mini_program_order_apply_response'], true);
        $data = [
            'appId' => $body['sp_app_id'],
            'timeStamp' => $body['sp_timestamp'],
            'nonceStr' => $body['sp_nonce_str'],
            'package' => $body['sp_packages'],
            'signType' => $body['sp_sign_type'],
            'paySign' => $body['sp_pay_sign'],
        ];

        return [$params, $response, json_encode($data, JSON_UNESCAPED_UNICODE)];
    }

    /**
     * 验证数据
     * @param array $params
     * @return array
     */
    public function verify(array $params): array
    {
        $sign = $params['sign'];
        unset($params['sign']);
        unset($params['sign_type']);
        $splic = splic($params);
        verify($splic, $sign, $this->getConfig('public_cert_path'));

        return $params;
    }

    /**
     * 退款
     * @param array $params
     * @return array
     */
    public function refund(array $params): array
    {
        $this->setConfig([
            'encrypt_fields' => [],
            'json_fields' => [
                'benefit_bean_list'
            ],
            'special_fields' => [
                'notify_url', 'remark', 'share_benefit_exp'
            ]
        ]);

        $params['service'] = 'fosun.sumpay.api.trade.refund';
        $params['mer_no'] = $this->getConfig('mer_no');

        [$params, $response, $body] = $this->request($params);
        $result = json_decode($body['sumpay_refund_response'], true);
        if (Arr::get($result, 'status') == '0') {
            throw new InternalException('REFUND FAIL');
        }

        return [$params, $response, $result];
    }

    /**
     * 查询订单
     * @param array $params
     * @return array
     */
    public function query(array $params): array
    {
        $params['service'] = 'fosun.sumpay.api.trade.order.search.merchant';
        $params['mer_no'] = $this->getConfig('mer_no');

        [$params, $response, $body] = $this->request($params);
        $result = json_decode($body['sumpay_order_search_merchant_response'], true);
        if (!$result || !Arr::has($result, 'status') || Arr::get($result, 'status') == '2') {
            throw new InternalException('PAY FAIL');
        }
        return [$params, $response, $result];
    }
}